package com.course.chapter4;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class CAS2 {
    private static AtomicInteger at =new AtomicInteger(100);
    private static AtomicStampedReference asr =new AtomicStampedReference(100,1);
    /**
     * 下面演示ABA问题
     * @param args
     */
    public static void main(String[] args) {
//        System.out.println(at.get());
//        Thread t1 = new Thread(() -> {
//            System.out.println(at.compareAndSet(100, 111));
//            System.out.println(at.get());
//        });
//        t1.start();
//        Thread t2 = new Thread(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(2);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println(at.compareAndSet(111, 100));
//            System.out.println(at.get());
//        });
//        t2.start();
//        Thread t3 = new Thread(() -> {
//            try {
//                TimeUnit.SECONDS.sleep(3);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println(at.compareAndSet(100, 120));
//            System.out.println(at.get());
//        });
//        t3.start();


        System.out.println("===========");
        System.out.println(asr.getReference());
        Thread tr1 = new Thread(() -> {
            int stamp = asr.getStamp();
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(asr.compareAndSet(100,110,stamp,stamp+1));
            System.out.println(asr.getReference());
        });
        tr1.start();
        Thread tr2 = new Thread(() -> {
            int stamp = asr.getStamp();
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(asr.compareAndSet(110,100,stamp,stamp+1));
            System.out.println(asr.getReference());
        });
        tr2.start();
        Thread tr3 = new Thread(() -> {
            int stamp = asr.getStamp();
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(asr.compareAndSet(100,110,stamp,stamp+1));
            System.out.println(asr.getReference());
        });
        tr3.start();
    }
}
